#include "Protocol.hpp"
#include "Socket.hpp"
#include <iostream>
#include <string>
#include <memory>
#include <ctime>
#include <unistd.h>

// ./tcpclient serverip serverport
int main(int argc, char *argv[])
{
    if(argc != 3)
    {
        std::cout << "Usage: " << argv[0] << " serverip serverport" << std::endl;
        return 0;
    }
    std::string serverip = argv[1];
    uint16_t serverport = std::stoi(argv[2]);

    std::unique_ptr<Socket> tsvr(new TcpSocket());
    if(!tsvr->BuildConnectSocketMethod(serverip, serverport))
    {
        std::cerr << "connect " << serverip << ":" << serverport << " failed" << std::endl;
        return 0;
    }
    std::cout << "connect " << serverip << ":" << serverport << " success" << std::endl; 

    std::unique_ptr<Factory> factory(new Factory());

    srand(time(nullptr) ^ getpid());
    std::string opers = "+-*/%-&=";     // 可能出现运算符（含有未定义操作符）

    while(true)
    {
        // 1. 构建自定义请求
        int x = rand() % 100; // [0, 99]
        usleep(rand()%7777);
        int y = rand() % 100; // [0, 99]
        char oper = opers[rand() % opers.size()];
        std::shared_ptr<Request> req = factory->BuildRequest(x, y, oper);
        // 2. 对请求进行序列化
        std::string reqstr; 
        req->Serialize(&reqstr);   
        // 3. 封装自定义报头
        std::string reqpackage = Encode(reqstr);      
        // 4. 发送
        tsvr->Send(reqpackage);

        std::string respackage;
        std::string responsestr;
        std::shared_ptr<Response> response = factory->BuildResponse();
        while(true)
        {
            // 读取响应
            if(!tsvr->Recv(&respackage, 1024)) break;  // 读取失败就直接退出
            // 解包
            if(!Decode(respackage, &responsestr)) continue;    // 解包失败就重新读            
            // 反序列化
            response->Deserialize(responsestr);
            std::cout << req->GetX() << req->GetOper() << req->GetY() << "=" << response->GetResult() \
                     << " [" << response->GetCode() << "]" << std::endl;
            break;  // 记得break
        }
    }

    tsvr->CloseSocket();

    return 0;
}